home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / 68kdis.zip / ISET.C < prev    next >
C/C++ Source or Header  |  1988-12-03  |  25KB  |  1,223 lines

  1. /*
  2.  *    SCCS:    @(#)iset.c    1.2    11/2/84    14:18:23
  3.  *    Decode instructions.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <a.out.h>
  28. #include <ldfcn.h>
  29. #include "unc.h"
  30.  
  31. ef_fids    mainfile;
  32. long    endt;
  33.  
  34. void    gette(), putte();
  35. void    mkdref();
  36. long    gettw();
  37. symbol    textlab();
  38.  
  39. int    l1(), l2(), el1(), lea(), lmove(), lcbch(), jj();
  40. int    limed(), lsbit(), lmvml(), lone(), loone(), lonew(), lonel();
  41.  
  42. int    pmove(), pcbch(), pdbcc(), pscc(), pcs(), pmovc(), pstop(), pexg();
  43. int    pimed(), pmovp(), psbit(), pdbit(), pcs2(), pone(), ppea();
  44. int    plea(), pdreg(), pmvml(), ptrap(), plink(), pareg(), podreg();
  45. int    pqu(), pmqu(), ptreg(), pcmpm(), pomode(), pmshf(), pshf();
  46.  
  47. struct    opstr    {
  48.     unsigned  short     mask;
  49.     unsigned  short  match;
  50.     int    (*opsize)();
  51.     int    (*opprin)();
  52.     char    *prarg;
  53. } optab[] = {
  54.     0xf000, 0x2000, lmove, pmove, ".l",
  55.     0xf000, 0x3000, lmove, pmove, ".w",
  56.     0xf000, 0x1000, lmove, pmove, ".b",
  57.     0xf000, 0x6000, lcbch, pcbch, 0,
  58.     0xffbf, 0x003c, l2,    pcs,   "or",
  59.     0xff00, 0x0000, limed, pimed, "or",
  60.     0xffbf, 0x023c, l2,    pcs,   "and",
  61.     0xff00, 0x0200, limed, pimed, "and",
  62.     0xff00, 0x0400, limed, pimed, "sub",
  63.     0xff00, 0x0600, limed, pimed, "add",
  64.     0xffbf, 0x0a3c, l2,    pcs,   "eor",
  65.     0xff00, 0x0a00, limed, pimed, "eor",
  66.     0xff00, 0x0c00, limed, pimed, "cmp",
  67.     0xf138, 0x0108, l2,    pmovp, 0,
  68.     0xff00, 0x0800, lsbit, psbit, 0,
  69.     0xf100, 0x0100, lonew, pdbit, 0,
  70.     0xffc0, 0x40c0, lonew, pcs2,  "sr",
  71.     0xff00, 0x4000, lone,  pone,  "negx",
  72.     0xff00, 0x4200, lone,  pone,  "clr",
  73.     0xffc0, 0x44c0, lonew, pcs2,  "cc",
  74.     0xff00, 0x4400, lone,  pone,  "neg",
  75.     0xffc0, 0x46c0, lonew, pcs2,  "sr",
  76.     0xff00, 0x4600, lone,  pone,  "not",
  77.     0xffc0, 0x4800, lonew, ppea,  "nbcd",
  78.     0xfff8, 0x4840, l1,    pdreg, "swap.w",
  79.     0xffc0, 0x4840, lonel, ppea,  "pea",
  80.     0xfff8, 0x4880, l1,    pdreg, "ext.w",
  81.     0xfff8, 0x48c0, l1,    pdreg, "ext.l",
  82.     0xfb80, 0x4880, lmvml, pmvml, 0,
  83.     0xffc0, 0x4ac0, lonew, ppea,  "tas",
  84.     0xff00, 0x4a00, lone,  pone,  "tst",
  85.     0xfff0, 0x4e40, l1,    ptrap, 0,
  86.     0xfff8, 0x4e50, l2,    plink, 0,
  87.     0xfff8, 0x4e58, l1,    pareg, "unlk\t%s",
  88.     0xfff8, 0x4e60, l1,    pareg, "mov.l\t%s,%%usp",
  89.     0xfff8, 0x4e68, l1,    pareg, "mov.l\t%%usp,%s",
  90.     0xffff, 0x4e70, l1,    pareg, "reset",
  91.     0xffff, 0x4e71, l1,    pareg, "nop",
  92.     0xffff, 0x4e72, l2,    pstop, 0,
  93.     0xffff, 0x4e73, el1,   pareg, "rte",
  94.     0xffff, 0x4e75, el1,   pareg, "rts",
  95.     0xffff, 0x4e76, l1,    pareg, "trapv",
  96.     0xffff, 0x4e77, el1,   pareg, "rtr",
  97.     0xfffe, 0x4e7a, l2,    pmovc, 0,
  98.     0xffc0, 0x4e80, jj,    ppea,  "jsr",
  99.     0xffc0, 0x4ec0, jj,    ppea,  "jmp",
  100.     0xf1c0, 0x4180, lonew, podreg,"chk",
  101.     0xf1c0, 0x41c0, lonel, plea,  0,
  102.     0xf0f8, 0x50c8, lcbch, pdbcc, 0,
  103.     0xf0c0, 0x50c0, lonew, pscc,  0,
  104.     0xf100, 0x5000, lone,  pqu,   "add",
  105.     0xf100, 0x5100, lone,  pqu,   "sub",
  106.     0xf100, 0x7000, l1,    pmqu,  0,
  107.     0xf1c0, 0x80c0, lonew, podreg,"divu",
  108.     0xf1c0, 0x81c0, lonew, podreg,"divs",
  109.     0xf1f0, 0x8100, l1,    ptreg, "sbcd",
  110.     0xf000, 0x8000, loone, pomode,"or",
  111.     0xf1f0, 0x9100, l1,    ptreg, "subx.b",
  112.     0xf1f0, 0x9140, l1,    ptreg, "subx.w",
  113.     0xf1f0, 0x9180, l1,    ptreg, "subx.l",
  114.     0xf000, 0x9000, loone, pomode,"sub",
  115.     0xf1f8, 0xb108, l1,    pcmpm, "cmp.b",        /* CMPM    */
  116.     0xf1f8, 0xb148, l1,    pcmpm, "cmp.w",        /* CMPM    */
  117.     0xf1f8, 0xb188, l1,    pcmpm, "cmp.l",        /* CMPM    */
  118.     0xf100, 0xb000, loone, pomode,"cmp",
  119.     0xf1c0, 0xb1c0, loone, pomode,"cmp",
  120.     0xf100, 0xb100, loone, pomode,"eor",
  121.     0xf1c0, 0xc0c0, lonew, podreg,"mulu",
  122.     0xf1c0, 0xc1c0, lonew, podreg,"muls",
  123.     0xf1f0, 0xc100, l1,    ptreg, "abcd",
  124.     0xf130, 0xc100, l1,    pexg,  0,
  125.     0xf000, 0xc000, loone, pomode,"and",
  126.     0xf1f0, 0xd100, l1,    ptreg, "addx.b",
  127.     0xf1f0, 0xd140, l1,    ptreg, "addx.w",
  128.     0xf1f0, 0xd180, l1,    ptreg, "addx.l",
  129.     0xf000, 0xd000, loone, pomode,"add",
  130.     0xf8c0, 0xe0c0, lonew, pmshf,  0,
  131.     0xf000, 0xe000, l1,    pshf,   0,
  132.     0
  133. };
  134.  
  135. char    *areg[] = { "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp"};
  136. char    *cclist[] = { "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs",
  137.             "pl", "mi", "ge", "lt", "gt", "le"};
  138.     
  139. char    *shtype[] = { "as", "ls", "rox", "ro" };
  140. char    *bittyp[] = { "tst", "chg", "clr", "set" };
  141.  
  142. char    *creg[] = { "%sfc", "%dfc", "%usp", "%vbr" };
  143.  
  144. int swbegflg = 0;
  145.  
  146. /*
  147.  *    Length functions.
  148.  */
  149.  
  150. int    l1()
  151. {
  152.     return    1;
  153. }
  154.  
  155. int    l2()
  156. {
  157.     return    2;
  158. }
  159.  
  160. int    el1(te)
  161. t_entry    *te;
  162. {
  163.     te->t_bchtyp = T_UNBR;
  164.     return    1;
  165. }
  166.  
  167. int    lea(instr, size, pos)
  168. unsigned  instr, size;
  169. long    pos;
  170. {
  171.     switch  ((instr >> 3) & 0x7)  {
  172.     case  0:
  173.     case  1:
  174.     case  2:
  175.     case  3:
  176.     case  4:
  177.         return    1;
  178.     case  5:
  179.     case  6:
  180.         return    2;
  181.     default:
  182.         switch  (instr & 0x7)  {
  183.         case  0:
  184.         case  2:
  185.         case  3:
  186.             return    2;
  187.         case  1:
  188.             mkdref(pos, size);
  189.             return    3;
  190.         case  4:
  191.             if  (size > 2)
  192.                 return    3;
  193.             return    2;
  194.         default:
  195.             return    0;
  196.         }
  197.     }
  198. }
  199.  
  200. /*
  201.  *    Lengths of move instructions.
  202.  */
  203.  
  204. int    lmove(te, pos)
  205. t_entry    *te;
  206. long    pos;
  207. {
  208.     register  unsigned  tc  =  te->t_contents;
  209.     unsigned  sz  =  1;
  210.     int    lng, lng2;
  211.     
  212.     lng  = tc & 0xf000;
  213.     if  (lng == 0x3000)
  214.         sz = 2;
  215.     else  if  (lng == 0x2000)
  216.         sz = 4;
  217.     
  218.     if  ((lng = lea(tc, sz, pos+2)) <= 0)
  219.         return    0;
  220.     lng2 = lea(((tc>>3) & 0x38) | ((tc>>9) & 0x7), sz, pos+lng+lng);
  221.     if  (lng2 <= 0)
  222.         return    0;
  223.     return    lng + lng2 - 1;
  224. }
  225.  
  226. /*
  227.  *    Lengths for conditional branches and dbcc instructions.
  228.  */
  229.  
  230. int    lcbch(te, pos)
  231. t_entry    *te;
  232. long    pos;
  233. {
  234.     unsigned  tc  =  te->t_contents;
  235.     long    dest  =  pos + 2;
  236.     int    res   =  2;
  237.     
  238.     if  ((tc & 0xf000) == 0x5000  ||  (tc & 0xff) == 0)
  239.         dest += (short)gettw(&mainfile, pos+2, R_WORD);
  240.     else  {
  241.         dest += (char) tc;
  242.         res = 1;
  243.     }
  244.      if ( dest < 0x290000 && (dest < mainfile.ef_tbase 
  245.          || dest >= mainfile.ef_tbase+mainfile.ef_tsize 
  246.          || (dest & 1) != 0 ))
  247.          return 0;        /* Illegal branch destination */
  248.     if  ((tc & 0xff00) == 0x6000)
  249.         te->t_bchtyp = T_UNBR;
  250.     else  if  ((tc & 0xff00) == 0x6100)
  251.         te->t_bchtyp = T_JSR;
  252.     else
  253.         te->t_bchtyp = T_CONDBR;
  254.  
  255.      if ( dest < 0x290000 && ((te->t_relsymb = textlab(dest, pos)) == NULL )) {
  256.          te->t_bchtyp = T_NOBR;/* Branch to a continuation */
  257.          return 0;
  258.      }
  259.     return    res;
  260. }
  261.  
  262. int    jj(te, pos)
  263. t_entry    *te;
  264. long    pos;
  265. {
  266.     unsigned  tc  =  te->t_contents;
  267.     t_entry    nextl;
  268.      long dest;
  269.     
  270.     te->t_bchtyp = (tc & 0x40)? T_UNBR: T_JSR;
  271.     if ((tc & 0x3f) == 0x39) {
  272.         gette(&mainfile, pos+2, &nextl);
  273.         if  (nextl.t_relsymb == NULL)  {
  274.              dest = gettw(&mainfile, pos + 2, R_LONG );
  275.              if ( dest < 0x290000 && (dest < mainfile.ef_tbase
  276.                  || dest >= mainfile.ef_tbase+mainfile.ef_tsize
  277.                  || (dest & 1) != 0 ))
  278.                  return 0;    /* Illegal branch destination */
  279.              if ( dest < 0x290000 && ( nextl.t_relsymb = textlab(dest, pos) ) == NULL )
  280.              return 0;    /* Branch to a continuation */
  281.             putte(&mainfile, pos+2, &nextl);
  282.         }
  283.         te->t_relsymb = nextl.t_relsymb;    /*  Easy ref  */
  284.     }
  285.     else if ((tc & 0x3f) == 0x3a) {
  286.         gette(&mainfile, pos+2, &nextl);
  287.         if  (nextl.t_relsymb == NULL)  {
  288.             dest = pos+2+ (int)((short) 
  289.                 gettw(&mainfile, pos + 2, R_WORD ));
  290.              if ( dest < 0x290000 && (dest < mainfile.ef_tbase
  291.                  || dest >= mainfile.ef_tbase+mainfile.ef_tsize
  292.                  || (dest & 1) != 0 ))
  293.             return    lea(tc, 4, pos+2);
  294.              if (dest < 0x290000 && 
  295.                 (nextl.t_relsymb = textlab(dest, pos)) == NULL)
  296.                  return 0;    /* Branch to a continuation */
  297.             putte(&mainfile, pos+2, &nextl);
  298.         }
  299.         te->t_relsymb = nextl.t_relsymb;    /*  Easy ref  */
  300.     }
  301.     return    lea(tc, 4, pos+2);
  302. }
  303.  
  304. int    limed(te, pos)
  305. t_entry    *te;
  306. long    pos;
  307. {
  308.     unsigned  tc  =  te->t_contents;
  309.     int    lng;
  310.     
  311.     /*
  312.      *    Specifically exclude byte address register operands,
  313.      *    and ones which have lengths of 3.
  314.      */
  315.  
  316.     if  ((tc & 0xf8) == 0x08)
  317.         return  0;
  318.     
  319.     if  ((tc & 0xc0) >= 0x80)  {
  320.         if  (tc & 0x40)
  321.             return  0;
  322.         lng = lea(tc, 4, pos+6);
  323.         if  (lng >